﻿Imports SlimDX
Imports SlimDX.Direct3D9
Imports Magic.Core
Imports System.IO

Public Class Scenario

    Public Enum netflags
        ctf_flag
        ctf_vehicle
        oddball_ball_spawn
        race_track
        race_vehicle
        vegas_bank
        teleport_from
        teleport_to
        hill_flag
        player_spawn
        ai_spawn
        ai_move
        cutscene_camera
    End Enum
    Structure hitObject
        Public blockName() As String
        Public hitIndex() As Integer
        Public Extension As String
        Sub Deselect()
            blockName = Nothing
            hitIndex = Nothing
            Extension = Nothing
        End Sub
    End Structure
    Class renderObject
        Public RenderObject As Object
        Public RenderMatrix As Matrix
        Public Render As Boolean

        Public Sub FinalRender()
            If Not RenderObject Is Nothing Then
                If Render Then
                    xDevice.MultiplyTransform(TransformState.World, RenderMatrix)
                    If RenderObject Is boxMesh Then
                        'boxMesh.DrawSubset(0)
                    ElseIf RenderObject.GetType Is GetType(Obje) Then
                        CType(RenderObject, Obje).Render(xDevice)
                    End If
                End If
            End If
        End Sub
        Public Sub OccludeRender()
            If Not RenderObject Is Nothing Then
                xDevice.SetTransform(TransformState.World, RenderMatrix)
                If RenderObject Is boxMesh Then
                    'boxMesh.DrawSubset(0)
                ElseIf RenderObject.GetType Is GetType(Obje) Then
                    CType(RenderObject, Obje).OccludeRender(xDevice)
                End If
            End If
        End Sub
    End Class
    Public ScenarioItems As New List(Of renderObject)
    Public BSPS() As BSP
    Public scnrTag As Tag
    Public skyModel As Model

    Public SelectedObject As New hitObject
    Public SelectedBSPIndex As Integer = 0
    Dim FogDensity, FogStart, FogEnd As Single
    Dim FogColor As Color

    Sub New(ByVal Tag As Magic.Core.Tag)

        AddHandler Tag.TagHasChanged, AddressOf Changed
        'WhiteTexture = New Bitmap(magicMap.Library(magicMap.Library.IndexByName("ui\shell\bitmaps\white", "bitm"))).Texture


        scnrTag = Tag
        Dim skyBlock As Array = Tag("skies")
        Dim skyCount As Integer = skyBlock.GetLength(0)
        If skyCount > 0 Then
            Dim skyIndex As Integer = skyBlock.GetValue(0, 0)
            If skyIndex > -1 Then
                Dim skyTag As Magic.Core.Tag = magicMap.Library(skyIndex)
                FogDensity = skyTag("outdoor fog maximum density:[0,1]")
                FogStart = skyTag("outdoor fog start distance:world units")
                FogEnd = skyTag("outdoor fog opaque distance:world units")
                FogColor = Color.FromArgb(skyTag("outdoor fog color")(0), skyTag("outdoor fog color")(1), skyTag("outdoor fog color")(2))
                If skyTag("model") > -1 Then skyModel = New Model(magicMap.Library(skyTag("model")))
            End If
        End If

        Dim bspBlock As Array = Tag("structure bsps")
        Dim bspCount As Integer = bspBlock.GetLength(0)
        ReDim BSPS(bspCount - 1)
        For x As Integer = 0 To bspCount - 1
            Dim bspTag As Magic.Core.Tag = magicMap.Library(bspBlock.GetValue(x, 4))
            BSPS(x) = New BSP(bspTag)
        Next
        SelectBSP(0)

        LoadScripts(scnrTag)
    End Sub
    Sub Changed(ByVal Tag As Magic.Core.Tag)

        'WhiteTexture = New Bitmap(magicMap.Library(magicMap.Library.IndexByName("ui\shell\bitmaps\white", "bitm"))).Texture


        scnrTag = Tag
        Dim skyBlock As Array = Tag("skies")
        Dim skyCount As Integer = skyBlock.GetLength(0)
        If skyCount > 0 Then
            Dim skyIndex As Integer = skyBlock.GetValue(0, 0)
            If skyIndex > -1 Then
                Dim skyTag As Magic.Core.Tag = magicMap.Library(skyIndex)
                FogDensity = skyTag("outdoor fog maximum density:[0,1]")
                FogStart = skyTag("outdoor fog start distance:world units")
                FogEnd = skyTag("outdoor fog opaque distance:world units")
                FogColor = Color.FromArgb(skyTag("outdoor fog color")(0), skyTag("outdoor fog color")(1), skyTag("outdoor fog color")(2))
                skyModel = New Model(magicMap.Library(skyTag("model")))
            End If
        End If

        Dim bspBlock As Array = Tag("structure bsps")
        Dim bspCount As Integer = bspBlock.GetLength(0)
        ReDim BSPS(bspCount - 1)
        For x As Integer = 0 To bspCount - 1
            Dim bspTag As Magic.Core.Tag = magicMap.Library(bspBlock.GetValue(x, 4))
            BSPS(x) = New BSP(bspTag)
        Next
        SelectBSP(0)


        'LoadScripts(scnrTag)
    End Sub
#Region "Add"
    Sub AddRed(ByVal sender As Object, ByVal e As EventArgs)

        Dim pClick As Point = CType(sender, ToolStripMenuItem).Owner.Tag

        Dim objBlock As Array = scnrTag("player starting locations")
        scnrTag("player starting locations") = scnrTag.Xpe.FieldByName("player starting locations").AddBlock(objBlock, -1)
        objBlock = scnrTag("player starting locations")

        Dim tIndex As Integer = objBlock.GetLength(0) - 1
        Dim pTranslation As Vector3 = BSPS(SelectedBSPIndex).GetVector(pClick.X, pClick.Y)
        objBlock.SetValue(New Single() {pTranslation.X, pTranslation.Y, pTranslation.Z}, tIndex, 0)
        objBlock.SetValue(0S, tIndex, 2)
        'Case "netgame flags"
        'Case "player starting locations"

    End Sub
    Sub AddBlue(ByVal sender As Object, ByVal e As EventArgs)

        Dim pClick As Point = CType(sender, ToolStripMenuItem).Owner.Tag

        Dim objBlock As Array = scnrTag("player starting locations")
        scnrTag("player starting locations") = scnrTag.Xpe.FieldByName("player starting locations").AddBlock(objBlock, -1)
        objBlock = scnrTag("player starting locations")

        Dim tIndex As Integer = objBlock.GetLength(0) - 1
        Dim pTranslation As Vector3 = BSPS(SelectedBSPIndex).GetVector(pClick.X, pClick.Y)
        objBlock.SetValue(New Single() {pTranslation.X, pTranslation.Y, pTranslation.Z}, tIndex, 0)
        objBlock.SetValue(1S, tIndex, 2)

    End Sub
    Sub AddPair(ByVal sender As Object, ByVal e As EventArgs)
        Dim pClick As Point = CType(sender, ToolStripMenuItem).Owner.Tag

        Dim objBlock As Array = scnrTag("netgame flags")

        'Find Highest Number first
        Dim teamIndex As Short = 0
        For x As Integer = 0 To objBlock.GetLength(0) - 1
            If objBlock.GetValue(x, 2) = 6 Or objBlock.GetValue(x, 2) = 7 Then
                If teamIndex <= objBlock.GetValue(x, 3) Then
                    teamIndex = objBlock.GetValue(x, 3) + 1
                End If
            End If
        Next

        scnrTag("netgame flags") = scnrTag.Xpe.FieldByName("netgame flags").AddBlock(objBlock, -1)
        objBlock = scnrTag("netgame flags")

        Dim tIndex As Integer = objBlock.GetLength(0) - 1
        Dim pTranslation As Vector3 = BSPS(SelectedBSPIndex).GetVector(pClick.X, pClick.Y)
        objBlock.SetValue(New Single() {pTranslation.X, pTranslation.Y, pTranslation.Z}, tIndex, 0)
        objBlock.SetValue(6S, tIndex, 2)
        objBlock.SetValue(teamIndex, tIndex, 3)

        scnrTag("netgame flags") = scnrTag.Xpe.FieldByName("netgame flags").AddBlock(objBlock, -1)
        objBlock = scnrTag("netgame flags")

        tIndex = objBlock.GetLength(0) - 1

        objBlock.SetValue(New Single() {pTranslation.X, pTranslation.Y, pTranslation.Z + 0.5}, tIndex, 0)
        objBlock.SetValue(7S, tIndex, 2)
        objBlock.SetValue(teamIndex, tIndex, 3)

    End Sub
#End Region
#Region "Occluding"

    Public Sub Occlude()

        'xDevice.SetRenderState(RenderState.FogEnable, True)
        'xDevice.SetRenderState(RenderState.FogVertexMode, FogMode.Linear)
        'xDevice.SetRenderState(RenderState.FogColor, FogColor.ToArgb)
        'xDevice.SetRenderState(RenderState.FogStart, FogStart)
        'xDevice.SetRenderState(RenderState.FogEnd, FogEnd)
        'xDevice.SetRenderState(RenderState.FogDensity, FogDensity)
        ScenarioItems.Clear()

        If appSettings.RenderAI Then
            OccludeItems(New String() {"squads", "move positions", "aimove"}, scnrTag("encounters"), scnrTag.Xpe.FieldByName("encounters"), Nothing)
            OccludeItems(New String() {"squads", "starting locations", "aispawn"}, scnrTag("encounters"), scnrTag.Xpe.FieldByName("encounters"), Nothing)
        End If
        If appSettings.Scenery Then
            OccludeItems(New String() {"palette"}, scnrTag("scenery"), scnrTag.Xpe.FieldByName("scenery"), scnrTag("scenery palette"))
        End If
        If appSettings.Bipeds Then
            OccludeItems(New String() {"palette"}, scnrTag("bipeds"), scnrTag.Xpe.FieldByName("bipeds"), scnrTag("biped palette"))
        End If
        If appSettings.Vehicles Then
            OccludeItems(New String() {"palette"}, scnrTag("vehicles"), scnrTag.Xpe.FieldByName("vehicles"), scnrTag("vehicle palette"))
        End If
        If appSettings.Equipment Then
            OccludeItems(New String() {"palette"}, scnrTag("equipment"), scnrTag.Xpe.FieldByName("equipment"), scnrTag("equipment palette"))
        End If
        If appSettings.Weapons Then
            OccludeItems(New String() {"palette"}, scnrTag("weapons"), scnrTag.Xpe.FieldByName("weapons"), scnrTag("weapon palette"))
        End If
        If appSettings.Machines Then
            OccludeItems(New String() {"palette"}, scnrTag("machines"), scnrTag.Xpe.FieldByName("machines"), scnrTag("machine palette"))
        End If
        If appSettings.Controls Then
            OccludeItems(New String() {"palette"}, scnrTag("controls"), scnrTag.Xpe.FieldByName("controls"), scnrTag("control palette"))
        End If
        If appSettings.LightFixtures Then
            OccludeItems(New String() {"palette"}, scnrTag("light fixtures"), scnrTag.Xpe.FieldByName("light fixtures"), scnrTag("light fixtures palette"))
        End If
        If appSettings.SoundScenery Then
            OccludeItems(New String() {"palette"}, scnrTag("sound scenery"), scnrTag.Xpe.FieldByName("sound scenery"), scnrTag("sound scenery palette"))
        End If
        If appSettings.RenderSpawn Then
            OccludeItems(New String() {"spawns"}, scnrTag("player starting locations"), scnrTag.Xpe.FieldByName("player starting locations"), Nothing)
        End If

        OccludeItems(New String() {"flags"}, scnrTag("netgame flags"), scnrTag.Xpe.FieldByName("netgame flags"), Nothing)
        OccludeItems(New String() {"equipment"}, scnrTag("netgame equipment"), scnrTag.Xpe.FieldByName("netgame equipment"), Nothing)

    End Sub
    Private Sub OccludeItems(ByVal blocks() As String, ByVal currentBlock As Array, ByVal currentField As Xpe.Field, ByVal palette As Array)
        If currentBlock Is Nothing Then Exit Sub
        Dim blockName As String = blocks(0)
        Dim objCount As Integer = currentBlock.GetLength(0)
        If blocks.Length = 1 Then
            Dim positionIndex As Integer = currentField.Item("position")
            Dim rotationIndex As Integer = currentField.Item("rotation")
            If rotationIndex = -1 Then
                rotationIndex = currentField.Item("facing:degress")
                If rotationIndex = -1 Then
                    rotationIndex = currentField.Item("facing:degrees")
                End If
            End If

            For x As Integer = 0 To objCount - 1
                Select Case blockName

                    Case "spawns", "aimove", "aispawn", "flags"
                        Dim pTranslation As Vector3 = New Vector3(currentBlock.GetValue(x, positionIndex)(0), currentBlock.GetValue(x, positionIndex)(1), currentBlock.GetValue(x, positionIndex)(2))
                        Dim pRotation As Single = currentBlock.GetValue(x, rotationIndex)
                        Dim pMatrix As Matrix = Matrix.Multiply(Matrix.Scaling(0.01F, 0.01F, 0.01F), Matrix.Multiply(Matrix.RotationYawPitchRoll(0, 0, pRotation), Matrix.Translation(pTranslation)))

                        Dim nRItem As New renderObject
                        nRItem.RenderMatrix = pMatrix
                        nRItem.RenderObject = boxMesh
                        ScenarioItems.Add(nRItem)

                    Case "equipment"
                        Dim pTranslation As Vector3 = New Vector3(currentBlock.GetValue(x, positionIndex)(0), currentBlock.GetValue(x, positionIndex)(1), currentBlock.GetValue(x, positionIndex)(2))
                        Dim pRotation As Single = currentBlock.GetValue(x, rotationIndex)
                        Dim pMatrix As Matrix = Matrix.Multiply(Matrix.RotationYawPitchRoll(0, 0, pRotation), Matrix.Translation(pTranslation))

                        Dim Index As Integer = currentBlock.GetValue(x, 10)
                        If Index > -1 Then
                            Dim itemBlock As Array = magicMap.Library(Index)("item permutations")
                            Dim itemCount As Integer = itemBlock.GetLength(0)
                            If itemCount > 0 Then
                                Dim nRItem As New renderObject
                                nRItem.RenderMatrix = pMatrix
                                nRItem.RenderObject = Managers.ReturnObject(itemBlock.GetValue(0, 2))
                                ScenarioItems.Add(nRItem)
                            End If
                        End If

                    Case "palette"
                        Dim objIndex As Integer = currentBlock.GetValue(x, 0)
                        If objIndex <> -1 Then

                            Dim pTranslation As Vector3 = New Vector3(currentBlock.GetValue(x, positionIndex)(0), currentBlock.GetValue(x, positionIndex)(1), currentBlock.GetValue(x, positionIndex)(2))
                            Dim pRotation As Vector3 = New Vector3(currentBlock.GetValue(x, rotationIndex)(0), currentBlock.GetValue(x, rotationIndex)(1), currentBlock.GetValue(x, rotationIndex)(2))
                            Dim pMatrix As Matrix = Matrix.Multiply(Matrix.RotationYawPitchRoll(pRotation.Y, pRotation.Z, pRotation.X), Matrix.Translation(pTranslation))

                            Dim nRItem As New renderObject
                            nRItem.RenderMatrix = pMatrix
                            nRItem.RenderObject = Managers.ReturnObject(palette.GetValue(objIndex, 0))
                            ScenarioItems.Add(nRItem)
                        End If
                End Select
            Next

        Else
            Dim nBlocks(blocks.Length - 2) As String
            Array.Copy(blocks, 1, nBlocks, 0, nBlocks.Length)

            For x As Integer = 0 To objCount - 1
                Dim objBlock As Array = CType(currentBlock.GetValue(x, currentField.Item(blockName)), Array)
                Dim objField As Magic.Core.Xpe.Field = currentField.FieldByName(blockName)

                OccludeItems(nBlocks, objBlock, objField, palette)
            Next
        End If
    End Sub
#End Region
#Region "Rendering"

    Public Sub Render()

        'xDevice.SetRenderState(RenderState.FogEnable, True)
        'xDevice.SetRenderState(RenderState.FogVertexMode, FogMode.Linear)
        'xDevice.SetRenderState(RenderState.FogColor, FogColor.ToArgb)
        'xDevice.SetRenderState(RenderState.FogStart, FogStart)
        'xDevice.SetRenderState(RenderState.FogEnd, FogEnd)
        'xDevice.SetRenderState(RenderState.FogDensity, FogDensity)
        If Not skyModel Is Nothing Then skyModel.Render(xDevice)
        BSPS(SelectedBSPIndex).Render(xDevice)
        'For x As Integer = 0 To ScenarioItems.Count - 1
        '    'ScenarioItems(x).Prepare()
        '    ScenarioItems(x).FinalRender()
        'Next
        If appSettings.RenderAI Then
            RenderItems(New String() {"squads", "move positions", "aimove"}, scnrTag("encounters"), scnrTag.Xpe.FieldByName("encounters"), Nothing)
            RenderItems(New String() {"squads", "starting locations", "aispawn"}, scnrTag("encounters"), scnrTag.Xpe.FieldByName("encounters"), Nothing)
        End If
        If appSettings.Scenery Then
            RenderItems(New String() {"palette"}, scnrTag("scenery"), scnrTag.Xpe.FieldByName("scenery"), scnrTag("scenery palette"))
        End If
        If appSettings.Bipeds Then
            RenderItems(New String() {"palette"}, scnrTag("bipeds"), scnrTag.Xpe.FieldByName("bipeds"), scnrTag("biped palette"))
        End If
        If appSettings.Vehicles Then
            RenderItems(New String() {"palette"}, scnrTag("vehicles"), scnrTag.Xpe.FieldByName("vehicles"), scnrTag("vehicle palette"))
        End If
        If appSettings.Equipment Then
            RenderItems(New String() {"palette"}, scnrTag("equipment"), scnrTag.Xpe.FieldByName("equipment"), scnrTag("equipment palette"))
        End If
        If appSettings.Weapons Then
            RenderItems(New String() {"palette"}, scnrTag("weapons"), scnrTag.Xpe.FieldByName("weapons"), scnrTag("weapon palette"))
        End If
        If appSettings.Machines Then
            RenderItems(New String() {"palette"}, scnrTag("machines"), scnrTag.Xpe.FieldByName("machines"), scnrTag("machine palette"))
        End If
        If appSettings.Controls Then
            RenderItems(New String() {"palette"}, scnrTag("controls"), scnrTag.Xpe.FieldByName("controls"), scnrTag("control palette"))
        End If
        If appSettings.LightFixtures Then
            RenderItems(New String() {"palette"}, scnrTag("light fixtures"), scnrTag.Xpe.FieldByName("light fixtures"), scnrTag("light fixtures palette"))
        End If
        If appSettings.SoundScenery Then
            RenderItems(New String() {"palette"}, scnrTag("sound scenery"), scnrTag.Xpe.FieldByName("sound scenery"), scnrTag("sound scenery palette"))
        End If
        If appSettings.RenderSpawn Then
            RenderItems(New String() {"spawns"}, scnrTag("player starting locations"), scnrTag.Xpe.FieldByName("player starting locations"), Nothing)
        End If

        RenderItems(New String() {"flags"}, scnrTag("netgame flags"), scnrTag.Xpe.FieldByName("netgame flags"), Nothing)
        RenderItems(New String() {"equipment"}, scnrTag("netgame equipment"), scnrTag.Xpe.FieldByName("netgame equipment"), Nothing)

    End Sub
    Private Sub RenderItems(ByVal blocks() As String, ByVal currentBlock As Array, ByVal currentField As Xpe.Field, ByVal palette As Array)
        If currentBlock Is Nothing Then Exit Sub
        Dim blockName As String = blocks(0)
        Dim objCount As Integer = currentBlock.GetLength(0)
        If blocks.Length = 1 Then
            Dim positionIndex As Integer = currentField.Item("position")
            Dim rotationIndex As Integer = currentField.Item("rotation")
            If rotationIndex = -1 Then
                rotationIndex = currentField.Item("facing:degress")
                If rotationIndex = -1 Then
                    rotationIndex = currentField.Item("facing:degrees")
                End If
            End If

            For x As Integer = 0 To objCount - 1
                Select Case blockName

                    Case "spawns"
                        Dim pTranslation As Vector3 = New Vector3(currentBlock.GetValue(x, positionIndex)(0), currentBlock.GetValue(x, positionIndex)(1), currentBlock.GetValue(x, positionIndex)(2))
                        Dim pRotation As Single = currentBlock.GetValue(x, rotationIndex)
                        Dim pMatrix As Matrix = Matrix.Multiply(Matrix.Scaling(0.01F, 0.01F, 0.01F), Matrix.Multiply(Matrix.RotationYawPitchRoll(0, 0, pRotation), Matrix.Translation(pTranslation)))

                        xDevice.SetTransform(TransformState.World, pMatrix)
                        Dim pointcolor As Color = appSettings.SpawnDefault
                        Select Case currentBlock.GetValue(x, 2)
                            Case 0, 2
                                pointcolor = appSettings.SpawnRed
                            Case 1, 3
                                pointcolor = appSettings.SpawnBlue
                        End Select
                        RenderBox(pointcolor)

                    Case "aimove"
                        Dim pTranslation As Vector3 = New Vector3(currentBlock.GetValue(x, positionIndex)(0), currentBlock.GetValue(x, positionIndex)(1), currentBlock.GetValue(x, positionIndex)(2))
                        Dim pRotation As Single = currentBlock.GetValue(x, rotationIndex)
                        Dim pMatrix As Matrix = Matrix.Multiply(Matrix.Scaling(0.01F, 0.01F, 0.01F), Matrix.Multiply(Matrix.RotationYawPitchRoll(0, 0, pRotation), Matrix.Translation(pTranslation)))

                        xDevice.SetTransform(TransformState.World, pMatrix)
                        RenderBox(appSettings.AIMove)

                    Case "aispawn"
                        Dim pTranslation As Vector3 = New Vector3(currentBlock.GetValue(x, positionIndex)(0), currentBlock.GetValue(x, positionIndex)(1), currentBlock.GetValue(x, positionIndex)(2))
                        Dim pRotation As Single = currentBlock.GetValue(x, rotationIndex)
                        Dim pMatrix As Matrix = Matrix.Multiply(Matrix.Scaling(0.01F, 0.01F, 0.01F), Matrix.Multiply(Matrix.RotationYawPitchRoll(0, 0, pRotation), Matrix.Translation(pTranslation)))

                        xDevice.SetTransform(TransformState.World, pMatrix)
                        RenderBox(appSettings.AISpawn)

                    Case "flags"
                        Dim pTranslation As Vector3 = New Vector3(currentBlock.GetValue(x, positionIndex)(0), currentBlock.GetValue(x, positionIndex)(1), currentBlock.GetValue(x, positionIndex)(2))
                        Dim pRotation As Single = currentBlock.GetValue(x, rotationIndex)
                        Dim pMatrix As Matrix = Matrix.Multiply(Matrix.Scaling(0.01F, 0.01F, 0.01F), Matrix.Multiply(Matrix.RotationYawPitchRoll(0, 0, pRotation), Matrix.Translation(pTranslation)))

                        xDevice.SetTransform(TransformState.World, pMatrix)
                        Select Case currentBlock.GetValue(x, 2)
                            Case netflags.ctf_flag, netflags.ctf_vehicle
                                If Not appSettings.RenderCTF Then Exit Select
                                RenderBox(appSettings.CTF)
                            Case netflags.hill_flag
                                If Not appSettings.RenderKOTH Then Exit Select
                                RenderBox(appSettings.KOTH)
                            Case netflags.oddball_ball_spawn
                                If Not appSettings.RenderOddball Then Exit Select
                                RenderBox(appSettings.Oddball)
                            Case netflags.race_track, netflags.race_vehicle
                                If Not appSettings.RenderRace Then Exit Select
                                RenderBox(appSettings.Race)
                            Case netflags.teleport_from, netflags.teleport_to
                                If Not appSettings.RenderTeleport Then Exit Select
                                RenderBox(appSettings.Teleport)
                        End Select

                    Case "equipment"
                        Dim pTranslation As Vector3 = New Vector3(currentBlock.GetValue(x, positionIndex)(0), currentBlock.GetValue(x, positionIndex)(1), currentBlock.GetValue(x, positionIndex)(2))
                        Dim pRotation As Single = currentBlock.GetValue(x, rotationIndex)
                        Dim pMatrix As Matrix = Matrix.Multiply(Matrix.RotationYawPitchRoll(0, 0, pRotation), Matrix.Translation(pTranslation))
                        xDevice.SetTransform(TransformState.World, pMatrix)

                        Dim Index As Integer = currentBlock.GetValue(x, 10)
                        If Index > -1 Then
                            Dim itemBlock As Array = magicMap.Library(Index)("item permutations")
                            Dim itemCount As Integer = itemBlock.GetLength(0)
                            If itemCount > 0 Then
                                Managers.ReturnObject(itemBlock.GetValue(0, 2)).Render(xDevice)
                            End If
                        End If

                    Case "palette"
                        Dim objIndex As Integer = currentBlock.GetValue(x, 0)
                        If objIndex <> -1 Then

                            Dim pTranslation As Vector3 = New Vector3(currentBlock.GetValue(x, positionIndex)(0), currentBlock.GetValue(x, positionIndex)(1), currentBlock.GetValue(x, positionIndex)(2))
                            Dim pRotation As Vector3 = New Vector3(currentBlock.GetValue(x, rotationIndex)(0), currentBlock.GetValue(x, rotationIndex)(1), currentBlock.GetValue(x, rotationIndex)(2))
                            Dim pMatrix As Matrix = Matrix.Multiply(Matrix.RotationYawPitchRoll(-pRotation.Y, pRotation.Z, pRotation.X), Matrix.Translation(pTranslation))

                            xDevice.SetTransform(TransformState.World, pMatrix)

                            Managers.ReturnObject(palette.GetValue(objIndex, 0)).Render(xDevice)
                        End If
                End Select
            Next

        Else
            Dim nBlocks(blocks.Length - 2) As String
            Array.Copy(blocks, 1, nBlocks, 0, nBlocks.Length)

            For x As Integer = 0 To objCount - 1
                Dim objBlock As Array = CType(currentBlock.GetValue(x, currentField.Item(blockName)), Array)
                Dim objField As Magic.Core.Xpe.Field = currentField.FieldByName(blockName)

                RenderItems(nBlocks, objBlock, objField, palette)
            Next
        End If
    End Sub
    Shared Sub RenderBox(ByVal pColor As Color)
        Dim pTranslation As New Vector3(xDevice.GetTransform(TransformState.World).M41, xDevice.GetTransform(TransformState.World).M42, xDevice.GetTransform(TransformState.World).M43)

        If BoxInFrustum(Vector3.Add(bBox_Max, pTranslation), Vector3.Add(bBox_Min, pTranslation)) Then
            shaderEffect.SetValue("pointColor", New Color4(pColor))
            shaderEffect.Technique = "boxMesh"

            shaderEffect.Begin(FX.DoNotSaveState)
            shaderEffect.BeginPass(0)
            boxMesh.DrawSubset(0)
            shaderEffect.EndPass()
            shaderEffect.End()
        End If
    End Sub
#End Region
#Region "Selection"
    Public Sub SelectBSP(ByVal Index As Integer)
        SelectedBSPIndex = Index
        Camera.Position = BSPS(Index).vCenter
    End Sub
    Public Sub SelectObject(ByVal pX As Integer, ByVal pY As Integer)

        Dim currentDistance As Single = Single.MaxValue
        Dim closestDistance As Single = Single.MaxValue
        Dim blockName() As String = Nothing
        Dim closestHit() As Integer = Nothing

        If appSettings.RenderAI Then
            SelectItems(New String() {"encounters", "squads", "move positions", "ai"}, Nothing, scnrTag("encounters"), scnrTag.Xpe.FieldByName("encounters"), Nothing, New Point(pX, pY), Nothing, blockName, closestHit, currentDistance, closestDistance)
            SelectItems(New String() {"encounters", "squads", "starting locations", "ai"}, Nothing, scnrTag("encounters"), scnrTag.Xpe.FieldByName("encounters"), Nothing, New Point(pX, pY), Nothing, blockName, closestHit, currentDistance, closestDistance)
        End If
        If appSettings.Scenery Then
            SelectItems(New String() {"scenery", "palette"}, Nothing, scnrTag("scenery"), scnrTag.Xpe.FieldByName("scenery"), scnrTag("scenery palette"), New Point(pX, pY), Nothing, blockName, closestHit, currentDistance, closestDistance)
        End If
        If appSettings.Bipeds Then
            SelectItems(New String() {"bipeds", "palette"}, Nothing, scnrTag("bipeds"), scnrTag.Xpe.FieldByName("bipeds"), scnrTag("biped palette"), New Point(pX, pY), Nothing, blockName, closestHit, currentDistance, closestDistance)
        End If
        If appSettings.Vehicles Then
            SelectItems(New String() {"vehicles", "palette"}, Nothing, scnrTag("vehicles"), scnrTag.Xpe.FieldByName("vehicles"), scnrTag("vehicle palette"), New Point(pX, pY), Nothing, blockName, closestHit, currentDistance, closestDistance)
        End If
        If appSettings.Equipment Then
            SelectItems(New String() {"equipment", "palette"}, Nothing, scnrTag("equipment"), scnrTag.Xpe.FieldByName("equipment"), scnrTag("equipment palette"), New Point(pX, pY), Nothing, blockName, closestHit, currentDistance, closestDistance)
        End If
        If appSettings.Weapons Then
            SelectItems(New String() {"weapons", "palette"}, Nothing, scnrTag("weapons"), scnrTag.Xpe.FieldByName("weapons"), scnrTag("weapon palette"), New Point(pX, pY), Nothing, blockName, closestHit, currentDistance, closestDistance)
        End If
        If appSettings.Machines Then
            SelectItems(New String() {"machines", "palette"}, Nothing, scnrTag("machines"), scnrTag.Xpe.FieldByName("machines"), scnrTag("machine palette"), New Point(pX, pY), Nothing, blockName, closestHit, currentDistance, closestDistance)
        End If
        If appSettings.Controls Then
            SelectItems(New String() {"controls", "palette"}, Nothing, scnrTag("controls"), scnrTag.Xpe.FieldByName("controls"), scnrTag("control palette"), New Point(pX, pY), Nothing, blockName, closestHit, currentDistance, closestDistance)
        End If
        If appSettings.LightFixtures Then
            SelectItems(New String() {"light fixtures", "palette"}, Nothing, scnrTag("light fixtures"), scnrTag.Xpe.FieldByName("light fixtures"), scnrTag("light fixtures palette"), New Point(pX, pY), Nothing, blockName, closestHit, currentDistance, closestDistance)
        End If
        If appSettings.SoundScenery Then
            SelectItems(New String() {"sound scenery", "palette"}, Nothing, scnrTag("sound scenery"), scnrTag.Xpe.FieldByName("sound scenery"), scnrTag("sound scenery palette"), New Point(pX, pY), Nothing, blockName, closestHit, currentDistance, closestDistance)
        End If
        If appSettings.RenderSpawn Then
            SelectItems(New String() {"player starting locations", "spawns"}, Nothing, scnrTag("player starting locations"), scnrTag.Xpe.FieldByName("player starting locations"), Nothing, New Point(pX, pY), Nothing, blockName, closestHit, currentDistance, closestDistance)
        End If

        SelectItems(New String() {"netgame flags", "flags"}, Nothing, scnrTag("netgame flags"), scnrTag.Xpe.FieldByName("netgame flags"), Nothing, New Point(pX, pY), Nothing, blockName, closestHit, currentDistance, closestDistance)
        SelectItems(New String() {"netgame equipment", "equipment"}, Nothing, scnrTag("netgame equipment"), scnrTag.Xpe.FieldByName("netgame equipment"), Nothing, New Point(pX, pY), Nothing, blockName, closestHit, currentDistance, closestDistance)

        If Not closestHit Is Nothing Then
            SelectedObject.blockName = blockName
            SelectedObject.hitIndex = closestHit
            Select Case SelectedScenario.SelectedObject.blockName(0)
                Case "scenery"
                    SelectedObject.Extension = "scenery"
                Case "bipeds"
                    SelectedObject.Extension = "biped"
                Case "vehicles"
                    SelectedObject.Extension = "vehicle"
                Case "netgame equipment"
                    SelectedObject.Extension = "item_collection"
                Case "weapons"
                    SelectedObject.Extension = "weapon"
                Case "machines"
                    SelectedObject.Extension = "device_machine"
                Case "controls"
                    SelectedObject.Extension = "device_control"
                Case "light fixtures"
                    SelectedObject.Extension = "light_fixture"
                Case "sound scenery"
                    SelectedObject.Extension = "sound_scenery"
                Case Else
                    SelectedObject.Extension = Nothing
            End Select
        Else
            SelectedObject.Deselect()
        End If

    End Sub
    Function CreateContext() As ContextMenuStrip
        Dim nContext As New ContextMenuStrip

        nContext.Items.Add("Add Object", Nothing, AddressOf AddObject)
        nContext.Items.Add("Add Red Spawn", Nothing, AddressOf AddRed)
        nContext.Items.Add("Add Blue Spawn", Nothing, AddressOf AddBlue)
        nContext.Items.Add("Add Teleporter Pair", Nothing, AddressOf AddPair)
        nContext.Items.Add(New ToolStripSeparator)
        If Not SelectedObject.blockName Is Nothing Then
            nContext.Items.Add("Copy Object", Nothing, AddressOf CopyObject)
            nContext.Items.Add("Delete Object", Nothing, AddressOf DeleteObject)
        Else
            Dim Copy As New ToolStripMenuItem("Copy Object")
            Copy.Enabled = False
            Dim Delete As New ToolStripMenuItem("Delete Object")
            Delete.Enabled = False
            nContext.Items.Add(Copy)
            nContext.Items.Add(Delete)

        End If
        nContext.Items.Add(New ToolStripSeparator)
        If Not SelectedObject.Extension Is Nothing Then

            nContext.Items.Add("Change Object", Nothing, AddressOf Change)
        Else
            Dim Change As New ToolStripMenuItem("Change Object")
            Change.Enabled = False
            nContext.Items.Add(Change)

        End If

        nContext.Items.Add(New ToolStripSeparator)
        nContext.Items.Add("Swap Shader", Nothing, AddressOf SwapShader)
        Return nContext
    End Function
    Sub SwapShader(ByVal sender As Object, ByVal e As EventArgs)
        Dim pClick As Point = CType(sender, ToolStripMenuItem).Owner.Tag
        Dim selectTag As New frmTag
        MagicInterface.DisplayTreeDB(selectTag.trvTags, My.Computer.FileSystem.GetFiles(appSettings.XboxTagFolder, FileIO.SearchOption.SearchAllSubDirectories, New String() {"*.shader*"}))
        If selectTag.ShowDialog = DialogResult.OK Then
            Dim tagDetail(1) As String
            tagDetail(0) = selectTag.trvTags.SelectedNode.FullPath.Replace(System.IO.Path.GetExtension(selectTag.trvTags.SelectedNode.FullPath), "")
            tagDetail(1) = cxpe.FromExtension(System.IO.Path.GetExtension(selectTag.trvTags.SelectedNode.FullPath).Replace(".", "")).FourCC
            Dim tagIndex As Integer = magicMap.Library.GetDependencyTag(tagDetail(0), tagDetail(1), appSettings.XboxTagFolder, appSettings.CETagFolder)
            BSPS(SelectedBSPIndex).SetShader(pClick.X, pClick.Y, tagIndex)

        End If
    End Sub
    Private Sub SelectItems(ByVal blocks() As String, ByVal hierarchy() As String, ByVal currentBlock As Array, ByVal currentField As Xpe.Field, ByVal palette As Array, ByVal hitPoint As Point, ByVal hitIndex() As Integer, ByRef bName() As String, ByRef hIndex() As Integer, ByRef currentDistance As Single, ByRef closestDistance As Single)
        If currentBlock Is Nothing Then Exit Sub
        If hierarchy Is Nothing Then
            hierarchy = blocks
            Dim tBlocks() As String = Array.CreateInstance(GetType(String), blocks.Length - 1)
            Array.Copy(blocks, 1, tBlocks, 0, tBlocks.Length)
            blocks = tBlocks
        End If
        Dim blockName As String = blocks(0)
        Dim objCount As Integer = currentBlock.GetLength(0)
        If blocks.Length = 1 Then
            Dim positionIndex As Integer = currentField.Item("position")
            Dim rotationIndex As Integer = currentField.Item("rotation")
            If rotationIndex = -1 Then
                rotationIndex = currentField.Item("facing:degress")
                If rotationIndex = -1 Then
                    rotationIndex = currentField.Item("facing:degrees")
                End If
            End If

            For x As Integer = 0 To objCount - 1
                Dim nHit() As Integer
                If hitIndex Is Nothing Then
                    nHit = New Integer() {x}
                Else
                    nHit = Array.CreateInstance(GetType(Integer), hitIndex.Length + 1)
                    Array.Copy(hitIndex, nHit, hitIndex.Length)
                    nHit(nHit.Length - 1) = x
                End If

                Dim n, f As Vector3
                n = New Vector3(CSng(hitPoint.X), CSng(hitPoint.Y), 0)
                f = New Vector3(CSng(hitPoint.X), CSng(hitPoint.Y), xDevice.Viewport.MaxZ)

                Select Case blockName

                    Case "spawns", "ai"
                        Dim pTranslation As Vector3 = New Vector3(currentBlock.GetValue(x, positionIndex)(0), currentBlock.GetValue(x, positionIndex)(1), currentBlock.GetValue(x, positionIndex)(2))
                        Dim pRotation As Single = currentBlock.GetValue(x, rotationIndex)
                        Dim pMatrix As Matrix = Matrix.Multiply(Matrix.Scaling(0.01F, 0.01F, 0.01F), Matrix.Multiply(Matrix.RotationYawPitchRoll(0, 0, pRotation), Matrix.Translation(pTranslation)))

Dim nRay As Ray = CreateRay(pmatrix, hitPoint.X, hitPoint.Y)
                        If boxMesh.Intersects(nRay, currentDistance) Then
                            If currentDistance < closestDistance Then
                                closestDistance = currentDistance
                                bName = hierarchy
                                hIndex = nHit
                            End If
                        End If


                    Case "flags"
                        Dim pTranslation As Vector3 = New Vector3(currentBlock.GetValue(x, positionIndex)(0), currentBlock.GetValue(x, positionIndex)(1), currentBlock.GetValue(x, positionIndex)(2))
                        Dim pRotation As Single = currentBlock.GetValue(x, rotationIndex)
                        Dim pMatrix As Matrix = Matrix.Multiply(Matrix.Scaling(0.01F, 0.01F, 0.01F), Matrix.Multiply(Matrix.RotationYawPitchRoll(0, 0, pRotation), Matrix.Translation(pTranslation)))

Dim nRay As Ray = CreateRay(pmatrix, hitPoint.X, hitPoint.Y)
                        Select Case currentBlock.GetValue(x, 2)
                            Case netflags.ctf_flag, netflags.ctf_vehicle
                                If Not appSettings.RenderCTF Then Exit Select
                                If boxMesh.Intersects(nRay, currentDistance) Then
                                    If currentDistance < closestDistance Then
                                        closestDistance = currentDistance
                                        bName = hierarchy
                                        hIndex = nHit
                                    End If
                                End If
                            Case netflags.hill_flag
                                If Not appSettings.RenderKOTH Then Exit Select
                                If boxMesh.Intersects(nRay, currentDistance) Then
                                    If currentDistance < closestDistance Then
                                        closestDistance = currentDistance
                                        bName = hierarchy
                                        hIndex = nHit
                                    End If
                                End If
                            Case netflags.oddball_ball_spawn
                                If Not appSettings.RenderOddball Then Exit Select
                                If boxMesh.Intersects(nRay, currentDistance) Then
                                    If currentDistance < closestDistance Then
                                        closestDistance = currentDistance
                                        bName = hierarchy
                                        hIndex = nHit
                                    End If
                                End If
                            Case netflags.race_track, netflags.race_vehicle
                                If Not appSettings.RenderRace Then Exit Select
                                If boxMesh.Intersects(nRay, currentDistance) Then
                                    If currentDistance < closestDistance Then
                                        closestDistance = currentDistance
                                        bName = hierarchy
                                        hIndex = nHit
                                    End If
                                End If
                            Case netflags.teleport_from, netflags.teleport_to
                                If Not appSettings.RenderTeleport Then Exit Select
                                If boxMesh.Intersects(nRay, currentDistance) Then
                                    If currentDistance < closestDistance Then
                                        closestDistance = currentDistance
                                        bName = hierarchy
                                        hIndex = nHit
                                    End If
                                End If
                        End Select

                    Case "equipment"
                        Dim pTranslation As Vector3 = New Vector3(currentBlock.GetValue(x, positionIndex)(0), currentBlock.GetValue(x, positionIndex)(1), currentBlock.GetValue(x, positionIndex)(2))
                        Dim pRotation As Single = currentBlock.GetValue(x, rotationIndex)
                        Dim pMatrix As Matrix = Matrix.Multiply(Matrix.RotationYawPitchRoll(0, 0, pRotation), Matrix.Translation(pTranslation))
                        Dim Index As Integer = currentBlock.GetValue(x, 10)
                        If Index > -1 Then
                            Dim itemBlock As Array = magicMap.Library(Index)("item permutations")
                            Dim itemCount As Integer = itemBlock.GetLength(0)
                            If itemCount > 0 Then
                                If Managers.ReturnObject(itemBlock.GetValue(0, 2)).Intercept(hitPoint.X, hitPoint.Y, pMatrix, currentDistance) Then
                                    If currentDistance < closestDistance Then
                                        closestDistance = currentDistance
                                        bName = hierarchy
                                        hIndex = nHit
                                    End If
                                End If
                            End If
                        End If

                    Case "palette"
                        Dim objIndex As Integer = currentBlock.GetValue(x, 0)
                        If objIndex <> -1 Then

                            Dim pTranslation As Vector3 = New Vector3(currentBlock.GetValue(x, positionIndex)(0), currentBlock.GetValue(x, positionIndex)(1), currentBlock.GetValue(x, positionIndex)(2))
                            Dim pRotation As Vector3 = New Vector3(currentBlock.GetValue(x, rotationIndex)(0), currentBlock.GetValue(x, rotationIndex)(1), currentBlock.GetValue(x, rotationIndex)(2))
                            Dim pMatrix As Matrix = Matrix.Multiply(Matrix.RotationYawPitchRoll(pRotation.Y, pRotation.Z, pRotation.X), Matrix.Translation(pTranslation))

                            If Managers.ReturnObject(palette.GetValue(objIndex, 0)).Intercept(hitPoint.X, hitPoint.Y, pMatrix, currentDistance) Then
                                If currentDistance < closestDistance Then
                                    closestDistance = currentDistance
                                    bName = hierarchy
                                    hIndex = nHit
                                End If
                            End If
                        End If
                End Select
            Next

        Else
            Dim nBlocks(blocks.Length - 2) As String
            Array.Copy(blocks, 1, nBlocks, 0, nBlocks.Length)

            For x As Integer = 0 To objCount - 1
                Dim objBlock As Array = CType(currentBlock.GetValue(x, currentField.Item(blockName)), Array)
                Dim objField As Magic.Core.Xpe.Field = currentField.FieldByName(blockName)
                Dim nHit() As Integer
                If hitIndex Is Nothing Then
                    nHit = New Integer() {x}
                Else
                    nHit = Array.CreateInstance(GetType(Integer), hitIndex.Length + 1)
                    Array.Copy(hitIndex, nHit, hitIndex.Length)
                    nHit(nHit.Length - 1) = x
                End If

                SelectItems(nBlocks, hierarchy, objBlock, objField, palette, hitPoint, nHit, bName, hIndex, currentDistance, closestDistance)
            Next
        End If
    End Sub
#End Region
#Region "Drag Drop"

    Public Sub DropObject(ByVal tagIndex As Integer, ByVal pX As Integer, ByVal pY As Integer)
        Dim droppedTag As Tag = magicMap.Library(tagIndex)

        Select Case droppedTag.Xpe.Extension
            Case "scenery"
                AddObject("scenery", "scenery palette", tagIndex, pX, pY)
            Case "biped"
                AddObject("bipeds", "biped palette", tagIndex, pX, pY)
            Case "vehicle"
                AddObject("vehicles", "vehicle palette", tagIndex, pX, pY)
            Case "equipment"
                AddObject("equipment", "equipment palette", tagIndex, pX, pY)
            Case "weapon"
                AddObject("weapons", "weapon palette", tagIndex, pX, pY)
            Case "device_machine"
                AddObject("machines", "machine palette", tagIndex, pX, pY)
            Case "device_control"
                AddObject("controls", "control palette", tagIndex, pX, pY)
            Case "light_fixture"
                AddObject("light fixtures", "light fixtures palette", tagIndex, pX, pY)
            Case "sound_scenery"
                AddObject("sound scenery", "sound scenery palette", tagIndex, pX, pY)
            Case "item_collection"
                AddCollection("netgame equipment", tagIndex, pX, pY)
            Case Else
                ConsoleMessage("Not a valid tag to drop.")
        End Select

    End Sub
    Private Sub AddCollection(ByVal blockName As String, ByVal tagIndex As Integer, ByVal pX As Integer, ByVal pY As Integer)

        Dim objBlock As Array = scnrTag(blockName)
        scnrTag(blockName) = scnrTag.Xpe.FieldByName(blockName).AddBlock(objBlock, -1)
        objBlock = scnrTag(blockName)

        Dim tIndex As Integer = objBlock.GetLength(0) - 1
        Dim pTranslation As Vector3 = BSPS(SelectedBSPIndex).GetVector(pX, pY)
        objBlock.SetValue(New Single() {pTranslation.X, pTranslation.Y, pTranslation.Z}, tIndex, 8)
        objBlock.SetValue(tagIndex, tIndex, 10)

    End Sub
    Private Sub AddObject(ByVal blockName As String, ByVal paletteName As String, ByVal tagIndex As Integer, ByVal pX As Integer, ByVal pY As Integer)
        Dim tagName As String = magicMap.Library.GetName(tagIndex).Trim(Chr(0))
        Dim paletteIndex As Integer = CType(scnrTag(paletteName), Array).GetLength(0) - 1
        If Not IsInObje(paletteName, tagName) Then
            paletteIndex = AddToPalette(paletteName, tagIndex)
        Else
            paletteIndex = ObjeIndex(paletteName, tagName)
        End If
        AddToBlock(blockName, paletteIndex, pX, pY)

    End Sub
    Private Function IsInObje(ByVal paletteName As String, ByVal dropTag As String) As Boolean
        Dim objBlock As Array = scnrTag(paletteName)
        Dim objCount As Integer = objBlock.GetLength(0)
        For x As Integer = 0 To objCount - 1
            Dim tIndex As Integer = objBlock.GetValue(x, 0)
            If tIndex > -1 Then
                If magicMap.Library(tIndex).Name = dropTag Then
                    Return True
                End If
            End If
        Next
        Return False
    End Function
    Private Function ObjeIndex(ByVal paletteName As String, ByVal dropTag As String) As Integer
        Dim objBlock As Array = scnrTag(paletteName)
        Dim objCount As Integer = objBlock.GetLength(0)
        For x As Integer = 0 To objCount - 1
            Dim tIndex As Integer = objBlock.GetValue(x, 0)
            If tIndex > -1 Then
                If magicMap.Library(tIndex).Name = dropTag Then
                    Return x
                End If
            End If
        Next
        Return -1
    End Function
    Private Function AddToPalette(ByVal PaletteName As String, ByVal tagIndex As Integer) As Integer
        Dim objBlock As Array = scnrTag(PaletteName)
        scnrTag(PaletteName) = scnrTag.Xpe.FieldByName(PaletteName).AddBlock(objBlock, -1)
        objBlock = scnrTag(PaletteName)
        Dim tIndex As Integer = objBlock.GetLength(0) - 1
        objBlock.SetValue(tagIndex, tIndex, 0)

        Return tIndex
    End Function
    Private Sub AddToBlock(ByVal blockName As String, ByVal paletteIndex As Integer, ByVal pX As Integer, ByVal pY As Integer)
        Dim objBlock As Array = scnrTag(blockName)
        scnrTag(blockName) = scnrTag.Xpe.FieldByName(blockName).AddBlock(objBlock, -1)
        objBlock = scnrTag(blockName)
        Dim tIndex As Integer = objBlock.GetLength(0) - 1
        objBlock.SetValue(CShort(paletteIndex), tIndex, 0)
        objBlock.SetValue(-1S, tIndex, 1)
        Dim pTranslation As Vector3 = BSPS(SelectedBSPIndex).GetVector(pX, pY)
        objBlock.SetValue(New Single() {pTranslation.X, pTranslation.Y, pTranslation.Z}, tIndex, 4)

    End Sub
#End Region
#Region "Copy"
    Public Sub CopyObject()
        If Not SelectedObject.blockName Is Nothing Then
            Dim nBlocks(SelectedObject.blockName.Length - 2) As String
            Array.Copy(SelectedObject.blockName, 1, nBlocks, 0, nBlocks.Length)
            CopyBlock(nBlocks, scnrTag(SelectedObject.blockName(0)), scnrTag.Xpe.FieldByName(SelectedObject.blockName(0)), scnrTag(SelectedObject.Extension), SelectedObject.hitIndex)

        End If
    End Sub
    Private Sub CopyBlock(ByVal blocks() As String, ByRef currentBlock As Array, ByVal currentField As Xpe.Field, ByVal palette As Array, ByVal hitIndex() As Integer)
        If currentBlock Is Nothing Then Exit Sub
        Dim blockName As String = blocks(0)
        Dim objCount As Integer = currentBlock.GetLength(0)
        If blocks.Length = 1 Then
            currentBlock = currentField.AddBlock(currentBlock, hitIndex(0))
        Else
            Dim nBlocks(blocks.Length - 2) As String
            Array.Copy(blocks, 1, nBlocks, 0, nBlocks.Length)

            Dim nHit(hitIndex.Length - 2) As Integer
            Array.Copy(hitIndex, 1, nHit, 0, nHit.Length)

            Dim objBlock As Array = CType(currentBlock.GetValue(hitIndex(0), currentField.Item(blockName)), Array)
            Dim objField As Magic.Core.Xpe.Field = currentField.FieldByName(blockName)

            CopyBlock(nBlocks, objBlock, objField, palette, nHit)
        End If
    End Sub
#End Region
#Region "Change"
    Public Sub AddObject(ByVal sender As Object, ByVal e As EventArgs)
        Dim pClick As Point = CType(sender, ToolStripMenuItem).Owner.Tag
        Dim selectTag As New frmTag
        MagicInterface.DisplayTreeDB(selectTag.trvTags, My.Computer.FileSystem.GetFiles(appSettings.XboxTagFolder, FileIO.SearchOption.SearchAllSubDirectories, New String() {"*.scenery", "*.biped", "*.vehicle", "*.item_collection", "*.weapon", "*.device_machine", "*.device_control", "*.light_fixture", "*.sound_scenery"}))
        If selectTag.ShowDialog = DialogResult.OK Then
            Dim tagDetail(1) As String
            tagDetail(0) = selectTag.trvTags.SelectedNode.FullPath.Replace(System.IO.Path.GetExtension(selectTag.trvTags.SelectedNode.FullPath), "")
            tagDetail(1) = cxpe.FromExtension(System.IO.Path.GetExtension(selectTag.trvTags.SelectedNode.FullPath).Replace(".", "")).FourCC
            Dim tagIndex As Integer = magicMap.Library.GetDependencyTag(tagDetail(0), tagDetail(1), appSettings.XboxTagFolder, appSettings.CETagFolder)

            Dim droppedTag As Tag = magicMap.Library(tagIndex)
            Select Case droppedTag.Xpe.Extension
                Case "scenery"
                    AddObject("scenery", "scenery palette", tagIndex, pClick.X, pClick.Y)
                Case "biped"
                    AddObject("bipeds", "biped palette", tagIndex, pClick.X, pClick.Y)
                Case "vehicle"
                    AddObject("vehicles", "vehicle palette", tagIndex, pClick.X, pClick.Y)
                Case "equipment"
                    AddObject("equipment", "equipment palette", tagIndex, pClick.X, pClick.Y)
                Case "weapon"
                    AddObject("weapons", "weapon palette", tagIndex, pClick.X, pClick.Y)
                Case "device_machine"
                    AddObject("machines", "machine palette", tagIndex, pClick.X, pClick.Y)
                Case "device_control"
                    AddObject("controls", "control palette", tagIndex, pClick.X, pClick.Y)
                Case "light_fixture"
                    AddObject("light fixtures", "light fixtures palette", tagIndex, pClick.X, pClick.Y)
                Case "sound_scenery"
                    AddObject("sound scenery", "sound scenery palette", tagIndex, pClick.X, pClick.Y)
                Case "item_collection"
                    AddCollection("netgame equipment", tagIndex, pClick.X, pClick.Y)
                Case Else
                    ConsoleMessage("Not a valid tag to add.")
            End Select

        End If
    End Sub
    Public Sub Change()
        Dim selectTag As New frmTag
        MagicInterface.DisplayTreeDB(selectTag.trvTags, My.Computer.FileSystem.GetFiles(appSettings.XboxTagFolder, FileIO.SearchOption.SearchAllSubDirectories, "*." & SelectedObject.Extension))
        If selectTag.ShowDialog = DialogResult.OK Then
            Dim tagDetail(1) As String
            tagDetail(0) = selectTag.trvTags.SelectedNode.FullPath.Replace(System.IO.Path.GetExtension(selectTag.trvTags.SelectedNode.FullPath), "")
            tagDetail(1) = cxpe.FromExtension(System.IO.Path.GetExtension(selectTag.trvTags.SelectedNode.FullPath).Replace(".", "")).FourCC
            Dim tagIndex As Short = magicMap.Library.GetDependencyTag(tagDetail(0), tagDetail(1), appSettings.XboxTagFolder, appSettings.CETagFolder)

            Dim droppedTag As Tag = magicMap.Library(tagIndex)
            Select Case droppedTag.Xpe.Extension
                Case "scenery"
                    ChangeObject("scenery", "scenery palette", tagIndex)
                Case "biped"
                    ChangeObject("bipeds", "biped palette", tagIndex)
                Case "vehicle"
                    ChangeObject("vehicles", "vehicle palette", tagIndex)
                Case "equipment"
                    ChangeObject("equipment", "equipment palette", tagIndex)
                Case "weapon"
                    ChangeObject("weapons", "weapon palette", tagIndex)
                Case "device_machine"
                    ChangeObject("machines", "machine palette", tagIndex)
                Case "device_control"
                    ChangeObject("controls", "control palette", tagIndex)
                Case "light_fixture"
                    ChangeObject("light fixtures", "light fixtures palette", tagIndex)
                Case "sound_scenery"
                    ChangeObject("sound scenery", "sound scenery palette", tagIndex)
                Case "item_collection"
                    If Not SelectedObject.blockName Is Nothing Then
                        Dim nBlocks(SelectedObject.blockName.Length - 2) As String
                        Array.Copy(SelectedObject.blockName, 1, nBlocks, 0, nBlocks.Length)
                        ChangeITMC(nBlocks, scnrTag(SelectedObject.blockName(0)), scnrTag.Xpe.FieldByName(SelectedObject.blockName(0)), scnrTag(SelectedObject.Extension), SelectedObject.hitIndex, tagIndex)
                    End If
            End Select

        End If
    End Sub
    Private Sub ChangeITMC(ByVal blocks() As String, ByVal currentBlock As Array, ByVal currentField As Xpe.Field, ByVal palette As Array, ByVal hitIndex() As Integer, ByVal value As Short)
        If currentBlock Is Nothing Then Exit Sub
        Dim blockName As String = blocks(0)
        Dim objCount As Integer = currentBlock.GetLength(0)
        If blocks.Length = 1 Then
            Dim positionIndex As Integer = currentField.Item("item collection")
            Dim x As Integer = hitIndex(0)
            currentBlock.SetValue(value, x, positionIndex)

        Else
            Dim nBlocks(blocks.Length - 2) As String
            Array.Copy(blocks, 1, nBlocks, 0, nBlocks.Length)

            Dim nHit(hitIndex.Length - 2) As Integer
            Array.Copy(hitIndex, 1, nHit, 0, nHit.Length)

            Dim objBlock As Array = CType(currentBlock.GetValue(hitIndex(0), currentField.Item(blockName)), Array)
            Dim objField As Magic.Core.Xpe.Field = currentField.FieldByName(blockName)

            ChangeObject(nBlocks, objBlock, objField, palette, nHit, value)
        End If

    End Sub
    Private Sub ChangeObject(ByVal blockName As String, ByVal paletteName As String, ByVal tagIndex As Short)
        Dim tagName As String = magicMap.Library.GetName(tagIndex).Trim(Chr(0))
        Dim paletteIndex As Integer = CType(scnrTag(paletteName), Array).GetLength(0) - 1
        If Not IsInObje(paletteName, tagName) Then
            paletteIndex = AddToPalette(paletteName, tagIndex)
        Else
            paletteIndex = ObjeIndex(paletteName, tagName)
        End If

        If Not SelectedObject.blockName Is Nothing Then
            Dim nBlocks(SelectedObject.blockName.Length - 2) As String
            Array.Copy(SelectedObject.blockName, 1, nBlocks, 0, nBlocks.Length)
            ChangeObject(nBlocks, scnrTag(SelectedObject.blockName(0)), scnrTag.Xpe.FieldByName(SelectedObject.blockName(0)), scnrTag(SelectedObject.Extension), SelectedObject.hitIndex, paletteIndex)
        End If

    End Sub
    Private Sub ChangeObject(ByVal blocks() As String, ByVal currentBlock As Array, ByVal currentField As Xpe.Field, ByVal palette As Array, ByVal hitIndex() As Integer, ByVal value As Short)
        If currentBlock Is Nothing Then Exit Sub
        Dim blockName As String = blocks(0)
        Dim objCount As Integer = currentBlock.GetLength(0)
        If blocks.Length = 1 Then
            Dim positionIndex As Integer = currentField.Item("type")
            Dim x As Integer = hitIndex(0)
            currentBlock.SetValue(value, x, positionIndex)

        Else
            Dim nBlocks(blocks.Length - 2) As String
            Array.Copy(blocks, 1, nBlocks, 0, nBlocks.Length)

            Dim nHit(hitIndex.Length - 2) As Integer
            Array.Copy(hitIndex, 1, nHit, 0, nHit.Length)

            Dim objBlock As Array = CType(currentBlock.GetValue(hitIndex(0), currentField.Item(blockName)), Array)
            Dim objField As Magic.Core.Xpe.Field = currentField.FieldByName(blockName)

            ChangeObject(nBlocks, objBlock, objField, palette, nHit, value)
        End If

    End Sub
#End Region
#Region "Move"
    Public Sub MoveObject(ByVal pX As Integer, ByVal pY As Integer)
        ObjectLocation = BSPS(SelectedBSPIndex).GetVector(pX, pY)

    End Sub
#End Region
#Region "Delete"
    Public Sub DeleteObject()
        If Not SelectedObject.blockName Is Nothing Then
            Dim nBlocks(SelectedObject.blockName.Length - 2) As String
            Array.Copy(SelectedObject.blockName, 1, nBlocks, 0, nBlocks.Length)
            DeleteBlock(nBlocks, scnrTag(SelectedObject.blockName(0)), scnrTag.Xpe.FieldByName(SelectedObject.blockName(0)), scnrTag(SelectedObject.Extension), SelectedObject.hitIndex)
            SelectedObject.Deselect()

        End If
    End Sub
    Private Sub DeleteBlock(ByVal blocks() As String, ByRef currentBlock As Array, ByVal currentField As Xpe.Field, ByVal palette As Array, ByVal hitIndex() As Integer)
        If currentBlock Is Nothing Then Exit Sub
        Dim blockName As String = blocks(0)
        Dim objCount As Integer = currentBlock.GetLength(0)
        If blocks.Length = 1 Then
            currentBlock = currentField.DeleteBlock(currentBlock, hitIndex(0))
        Else
            Dim nBlocks(blocks.Length - 2) As String
            Array.Copy(blocks, 1, nBlocks, 0, nBlocks.Length)

            Dim nHit(hitIndex.Length - 2) As Integer
            Array.Copy(hitIndex, 1, nHit, 0, nHit.Length)

            Dim objBlock As Array = CType(currentBlock.GetValue(hitIndex(0), currentField.Item(blockName)), Array)
            Dim objField As Magic.Core.Xpe.Field = currentField.FieldByName(blockName)

            DeleteBlock(nBlocks, objBlock, objField, palette, nHit)
        End If

    End Sub
#End Region
#Region "Properties"
    Public ReadOnly Property ObjectSelected() As Boolean
        Get
            Return Not SelectedObject.blockName Is Nothing
        End Get
    End Property
    Public Property ObjectLocation() As Vector3
        Get
            If Not SelectedObject.blockName Is Nothing Then
                Dim nBlocks(SelectedObject.blockName.Length - 2) As String
                Array.Copy(SelectedObject.blockName, 1, nBlocks, 0, nBlocks.Length)
                Return GetPosition(nBlocks, scnrTag(SelectedObject.blockName(0)), scnrTag.Xpe.FieldByName(SelectedObject.blockName(0)), scnrTag(SelectedObject.Extension), SelectedObject.hitIndex)
            End If
            Return New Vector3(0, 0, 0)
        End Get
        Set(ByVal value As Vector3)
            If Not SelectedObject.blockName Is Nothing Then
                Dim nBlocks(SelectedObject.blockName.Length - 2) As String
                Array.Copy(SelectedObject.blockName, 1, nBlocks, 0, nBlocks.Length)
                SetPosition(nBlocks, scnrTag(SelectedObject.blockName(0)), scnrTag.Xpe.FieldByName(SelectedObject.blockName(0)), scnrTag(SelectedObject.Extension), SelectedObject.hitIndex, value)
            End If
        End Set

    End Property
    Private Function GetPosition(ByVal blocks() As String, ByVal currentBlock As Array, ByVal currentField As Xpe.Field, ByVal palette As Array, ByVal hitIndex() As Integer) As Vector3
        If currentBlock Is Nothing Then Exit Function
        Dim blockName As String = blocks(0)
        Dim objCount As Integer = currentBlock.GetLength(0)
        If blocks.Length = 1 Then
            Dim positionIndex As Integer = currentField.Item("position")
            Dim x As Integer = hitIndex(0)
            Dim pTranslation As Vector3 = New Vector3(currentBlock.GetValue(x, positionIndex)(0), currentBlock.GetValue(x, positionIndex)(1), currentBlock.GetValue(x, positionIndex)(2))
            Return pTranslation

        Else
            Dim nBlocks(blocks.Length - 2) As String
            Array.Copy(blocks, 1, nBlocks, 0, nBlocks.Length)

            Dim nHit(hitIndex.Length - 2) As Integer
            Array.Copy(hitIndex, 1, nHit, 0, nHit.Length)

            Dim objBlock As Array = CType(currentBlock.GetValue(hitIndex(0), currentField.Item(blockName)), Array)
            Dim objField As Magic.Core.Xpe.Field = currentField.FieldByName(blockName)

            Return GetPosition(nBlocks, objBlock, objField, palette, nHit)
        End If
    End Function
    Private Sub SetPosition(ByVal blocks() As String, ByVal currentBlock As Array, ByVal currentField As Xpe.Field, ByVal palette As Array, ByVal hitIndex() As Integer, ByVal value As Vector3)
        If currentBlock Is Nothing Then Exit Sub
        Dim blockName As String = blocks(0)
        Dim objCount As Integer = currentBlock.GetLength(0)
        If blocks.Length = 1 Then
            Dim positionIndex As Integer = currentField.Item("position")
            Dim x As Integer = hitIndex(0)
            currentBlock.SetValue(New Single() {value.X, value.Y, value.Z}, x, positionIndex)

        Else
            Dim nBlocks(blocks.Length - 2) As String
            Array.Copy(blocks, 1, nBlocks, 0, nBlocks.Length)

            Dim nHit(hitIndex.Length - 2) As Integer
            Array.Copy(hitIndex, 1, nHit, 0, nHit.Length)

            Dim objBlock As Array = CType(currentBlock.GetValue(hitIndex(0), currentField.Item(blockName)), Array)
            Dim objField As Magic.Core.Xpe.Field = currentField.FieldByName(blockName)

            SetPosition(nBlocks, objBlock, objField, palette, nHit, value)
        End If
    End Sub

    Public Property ObjectRotation() As Vector3
        Get
            If Not SelectedObject.blockName Is Nothing Then
                Dim nBlocks(SelectedObject.blockName.Length - 2) As String
                Array.Copy(SelectedObject.blockName, 1, nBlocks, 0, nBlocks.Length)
                Return GetRotation(nBlocks, scnrTag(SelectedObject.blockName(0)), scnrTag.Xpe.FieldByName(SelectedObject.blockName(0)), scnrTag(SelectedObject.Extension), SelectedObject.hitIndex)
            End If
            Return New Vector3(0, 0, 0)
        End Get
        Set(ByVal value As Vector3)
            If Not SelectedObject.blockName Is Nothing Then
                Dim nBlocks(SelectedObject.blockName.Length - 2) As String
                Array.Copy(SelectedObject.blockName, 1, nBlocks, 0, nBlocks.Length)
                SetRotation(nBlocks, scnrTag(SelectedObject.blockName(0)), scnrTag.Xpe.FieldByName(SelectedObject.blockName(0)), scnrTag(SelectedObject.Extension), SelectedObject.hitIndex, value)
            End If
        End Set
    End Property
    Private Function GetRotation(ByVal blocks() As String, ByVal currentBlock As Array, ByVal currentField As Xpe.Field, ByVal palette As Array, ByVal hitIndex() As Integer) As Vector3
        If currentBlock Is Nothing Then Exit Function
        Dim blockName As String = blocks(0)
        Dim objCount As Integer = currentBlock.GetLength(0)
        If blocks.Length = 1 Then
            Dim rotationIndex As Integer = currentField.Item("rotation")
            If rotationIndex = -1 Then
                rotationIndex = currentField.Item("facing:degress")
                If rotationIndex = -1 Then
                    rotationIndex = currentField.Item("facing:degrees")
                End If
                Return New Vector3(currentBlock.GetValue(hitIndex(0), rotationIndex), 0, 0)
            Else
                Return New Vector3(currentBlock.GetValue(hitIndex(0), rotationIndex)(0), currentBlock.GetValue(hitIndex(0), rotationIndex)(1), currentBlock.GetValue(hitIndex(0), rotationIndex)(2))
            End If

        Else
            Dim nBlocks(blocks.Length - 2) As String
            Array.Copy(blocks, 1, nBlocks, 0, nBlocks.Length)

            Dim nHit(hitIndex.Length - 2) As Integer
            Array.Copy(hitIndex, 1, nHit, 0, nHit.Length)

            Dim objBlock As Array = CType(currentBlock.GetValue(hitIndex(0), currentField.Item(blockName)), Array)
            Dim objField As Magic.Core.Xpe.Field = currentField.FieldByName(blockName)

            Return GetRotation(nBlocks, objBlock, objField, palette, nHit)
        End If
    End Function
    Private Sub SetRotation(ByVal blocks() As String, ByVal currentBlock As Array, ByVal currentField As Xpe.Field, ByVal palette As Array, ByVal hitIndex() As Integer, ByVal value As Vector3)
        If currentBlock Is Nothing Then Exit Sub
        Dim blockName As String = blocks(0)
        Dim objCount As Integer = currentBlock.GetLength(0)
        If blocks.Length = 1 Then
            Dim x As Integer = hitIndex(0)

            Dim rotationIndex As Integer = currentField.Item("rotation")
            If rotationIndex = -1 Then
                rotationIndex = currentField.Item("facing:degress")
                If rotationIndex = -1 Then
                    rotationIndex = currentField.Item("facing:degrees")
                End If
                currentBlock.SetValue(value.X, x, rotationIndex)
            Else
                currentBlock.SetValue(New Single() {value.X, value.Y, value.Z}, x, rotationIndex)
            End If
        Else
            Dim nBlocks(blocks.Length - 2) As String
            Array.Copy(blocks, 1, nBlocks, 0, nBlocks.Length)

            Dim nHit(hitIndex.Length - 2) As Integer
            Array.Copy(hitIndex, 1, nHit, 0, nHit.Length)

            Dim objBlock As Array = CType(currentBlock.GetValue(hitIndex(0), currentField.Item(blockName)), Array)
            Dim objField As Magic.Core.Xpe.Field = currentField.FieldByName(blockName)

            SetRotation(nBlocks, objBlock, objField, palette, nHit, value)
        End If
    End Sub
#End Region

End Class
